#include "Mover.h"
#include <utils/XString.h>
#include <dao/Connections.h>
#include <config/Config.h>
#include <utils/XTimer.h>
#include <sys/wait.h>

using namespace std;
using namespace dbinfo;
using namespace articleInfo;
using namespace chapterInfo;
using namespace mover;

Mover::Mover(void)
{
  m_articleListSource = new ArticleInfo[SIZE_ARTICLE_LIST];
  m_chapterListTarget = new ChapterInfo[SIZE_CHAPTER_LIST];
  m_chapterListSource = new ChapterInfo[SIZE_CHAPTER_LIST];
}

Mover::~Mover(void)
{
  if( m_articleListSource != NULL)
  {
    delete[] m_articleListSource;
    m_articleListSource = NULL;
  }
  if( m_chapterListTarget != NULL)
  {
    delete[] m_chapterListTarget;
    m_chapterListTarget = NULL;
  }
  if(m_chapterListSource != NULL)
  {
    delete[] m_chapterListSource;
    m_chapterListSource = NULL;
  }
  map<string, DaoArticle*>::iterator itArticle = m_mapsArticleDAO.begin();
  for(;itArticle != m_mapsArticleDAO.end(); ++itArticle)
  {
    delete itArticle->second;
    itArticle->second = NULL;
  }
  map<string, DaoChapter*>::iterator itChapter = m_mapsChapterDAO.begin();
  for(;itChapter != m_mapsChapterDAO.end(); ++itChapter)
  {
    delete itChapter->second;
    itChapter->second = NULL;
  }
  map<string, Builder*>::iterator itBuilder = m_mapsBuilder.begin();
  for(;itBuilder != m_mapsBuilder.end(); ++itBuilder)
  {
    delete itBuilder->second;
    itBuilder->second = NULL;
  }
}

void Mover::initialize()
{
  //  memset((void *)&m_articleTarget, 0x00, sizeof(m_articleTarget));
  //  memset((void *)m_articleListSource, 0x00, sizeof(m_articleListSource));
  //  memset((void *)m_chapterListTarget, 0x00, sizeof(m_chapterListTarget));
  //  memset((void *)m_chapterListSource, 0x00, sizeof(m_chapterListSource));
}

void Mover::addDAO(const std::string& target, const std::string& source)
{
  MYSQL* conn = Connections::getInstance()->getConnection(source);
  DaoArticle* articleDao = new DaoArticle(conn);
  DaoChapter* chapterDao = new DaoChapter(conn);
  DaoAttach* attachDao = new DaoAttach(conn);
  m_mapsArticleDAO[source] = articleDao;
  m_mapsChapterDAO[source] = chapterDao;
  m_mapsAttachDAO[source] = attachDao;

  conn = Connections::getInstance()->getConnection(target);
  articleDao = new DaoArticle(conn);
  chapterDao = new DaoChapter(conn);
  attachDao = new DaoAttach(conn);
  m_mapsArticleDAO[target] = articleDao;
  m_mapsChapterDAO[target] = chapterDao;
  m_mapsAttachDAO[target] = attachDao;
  //add by san
}

void Mover::addBuilder(const configInfo::ConfigInfo& config)
{
  Builder* builder = new Builder(config);
  builder->loadConfig();
  builder->loadTheme();
  m_mapsBuilder[config.flag] = builder;
}

void Mover::analyseNextPage(const int flag, const int posBegin)
{
  if(flag == 1)//查找上一章节
  {
    for(int i = posBegin - 1; i >= 0 ; i--)
    {
      if(m_chapterListTarget[i].chaptertype == '0')
      {
        m_chapterListTarget[posBegin].preview_page.assign(m_chapterListTarget[i].chapterid);
        return;
      }
    }
  }
  else if(flag == 2) //查找下一章节
  {
    for(int i= posBegin + 1; i < m_targetChapterRecCount; ++i)
    {
      if(m_chapterListTarget[i].chaptertype == '0')
      {
        m_chapterListTarget[posBegin].next_page.assign(m_chapterListTarget[i].chapterid);
        return;
      }
    }
  }
}

void Mover::working()
{
#define Configer Config::getInstance()
  m_configLen = Configer->getSize();
  static string sourceFlag = Configer->getConfig()->flag + "source";
  for(int ci = 0; ci < m_configLen && Configer->getOffon(); ++ci)
  {
    if(Configer->getConfig(ci)->isactive == 0)
    {
      continue;
    }
    if(m_mapsArticleDAO.find(Configer->getConfig(ci)->flag + "target") == m_mapsArticleDAO.end()
       && m_mapsChapterDAO.find(Configer->getConfig(ci)->flag + "target") == m_mapsChapterDAO.end())
    {
      addDAO(Configer->getConfig(ci)->flag + "target", sourceFlag);
    }
    if(m_mapsBuilder.find(Configer->getConfig(ci)->flag) == m_mapsBuilder.end())
    {
      addBuilder(*(Configer->getConfig(ci)));
    }
    m_currentConfig = Configer->getConfig(ci);
    m_flagSource = sourceFlag;
    m_flagTarget = m_currentConfig->flag + "target";
    m_flag = Configer->getConfig(ci)->flag ;
    printf("[%s]->Begin copy.\n", m_currentConfig->flag.c_str());
    getNovelList();
    printf("[%s]->Complete copy.\n", m_currentConfig->flag.c_str());
  }
}

void Mover::getNovelList()
{
  if(m_mapsArticleID.find(m_currentConfig->flag) == m_mapsArticleID.end())
  {
    m_mapsArticleDAO[m_flagTarget]->getArticleMaxID(m_mapsArticleID[m_currentConfig->flag]);
  }
  if(m_mapsChapterID.find(m_currentConfig->flag) == m_mapsChapterID.end())
  {
    m_mapsChapterDAO[m_flagTarget]->getChapterMaxID(m_mapsChapterID[m_currentConfig->flag]);
  }
  if(m_mapsAttachID.find(m_currentConfig->flag) == m_mapsAttachID.end())
  {
    m_mapsAttachDAO[m_flagTarget]->getAttachMaxID(m_mapsAttachID[m_currentConfig->flag]);
  }
  int sourceArticleRecCount = 0;
  //  memset((void*)m_articleListSource, 0x00, sizeof(m_articleListSource));
  sourceArticleRecCount = m_mapsArticleDAO[m_flagSource]->getArticleList(m_currentConfig->lastupdate, m_articleListSource);
  if(sourceArticleRecCount == -1)
  {
    usleep(m_currentConfig->sleeptimes * 1000);
    return;
  }
  printf("article count:%d\n", sourceArticleRecCount);
  m_repeatTimes = 0;  //重复次数置零
  for(m_articleIndex = 0; m_articleIndex < sourceArticleRecCount
      && m_repeatTimes < m_currentConfig->repeatmax
      && Configer->getOffon(); ++m_articleIndex)
  {
    printf("[->30109<-] 开始采集 %s\n", m_articleListSource[m_articleIndex].articlename.c_str());
    if (getNovel())
    {
      getChapterList();
      completeNovel();
      Config::getInstance()->saveXml(m_articleListSource[m_articleIndex].lastupdate, m_flag);
//      Utils::saveConfigs(m_configs);
    }
    printf("[->30108<-] 结束采集 %s\n", m_articleListSource[m_articleIndex].articlename.c_str());
  }
}

bool Mover::getNovel()
{
  m_articleExists = false;
  resetInteriorVariable();
  m_articleExists = m_mapsArticleDAO[m_flagTarget]->getArticle(m_articleListSource[m_articleIndex].articlename, m_articleTarget);
  if (m_articleExists == false)
  {
    //    memset((void*)&m_articleTarget, 0x00, sizeof(m_articleTarget));
    assignArticle(m_articleListSource[m_articleIndex], m_articleTarget);
    resetArticle();
  }
  m_sourceChapterRecCount = m_mapsChapterDAO[m_flagSource]->getChapterList(m_articleListSource[m_articleIndex], m_chapterListSource);
  //  if (!m_mapsChapterDAO[m_flagSource]->getChapterList(m_articleListSource[m_articleIndex], m_chapterListSource, m_sourceChapterRecCount))
  //  {
  //    return false;
  //  }
  m_opfBuilder.addMetadata(m_articleTarget);
  if(m_articleExists)
  {
    m_targetChapterRecCount = m_mapsChapterDAO[m_flagTarget]->getChapterList(m_articleTarget, m_chapterListTarget);
    //    if(!m_mapsChapterDAO[m_flagTarget]->getChapterList(m_articleTarget, m_chapterListTarget, m_targetChapterRecCount))
    //    {
    //      return false;
    //    }
    printf("chapter count:%d\n", m_targetChapterRecCount);
    m_lastTargetChapterCount = m_targetChapterRecCount;
    if(m_targetChapterRecCount == m_sourceChapterRecCount)
    {
      m_repeatTimes++;
      m_currentConfig->lastupdate.assign(m_articleListSource[m_articleIndex].lastupdate);
//      Config::getInstance()->setLastUpdate(m_articleListSource[m_articleIndex].lastupdate);
      return false;
    }
  }
  else
  {
    static char txtLink[1024] = {0};
    sprintf(txtLink, "%s/files/article/txtfull/%d/%s.txt",
            m_currentConfig->targetdomain.c_str(),
            boost::lexical_cast<int>(m_articleListSource[m_articleIndex].articleid) / SIZE_FILE_SPLIT_UNIT,
            m_articleListSource[m_articleIndex].articleid.c_str());
    m_articleTarget.downloadlink.assign(txtLink);
  }
  return true;
}

void Mover::getChapterList()
{
  for (int ci = 0; ci < m_sourceChapterRecCount; ++ci)
  {
    if (m_targetChapterRecCount > ci)
    {
      m_opfBuilder.addMainfestAndSpine(m_chapterListTarget[ci]);
    }
    else
    {
      assignChapter(m_chapterListSource[ci], m_chapterListTarget[ci]);
      m_chapterListTarget[ci].articleid = m_articleTarget.articleid;
      m_chapterListTarget[ci].chapterid = m_mapsChapterID[m_flag];
      m_chapterListTarget[ci].isnew = '1';
      m_mapsChapterDAO[m_flagTarget]->addChapterCache(m_chapterListTarget[ci]);
      maxIDAutoPlus(m_mapsChapterID[m_flag]);
      m_targetChapterRecCount++;
    }
  }
}

void Mover::getAttachList(const chapterInfo::ChapterInfo& sourceChapter,
                          const chapterInfo::ChapterInfo& targetChapter)
{
  int len = m_mapsAttachDAO[m_flagSource]->getAttachList(sourceChapter, m_attachListSource);
  for(int aindex=0 ; aindex < len ;++aindex)
  {
    m_attachListTarget[aindex].articleid = targetChapter.articleid;
    m_attachListTarget[aindex].chapterid = targetChapter.chapterid;
    m_attachListTarget[aindex].attachid =  m_mapsAttachID[m_flag];
    m_attachListTarget[aindex].cname = m_attachListSource[aindex].cname;
    m_attachListTarget[aindex].cclass = m_attachListSource[aindex].cclass;
    m_attachListTarget[aindex].postfix= m_attachListSource[aindex].postfix;
    m_attachListTarget[aindex].csize= m_attachListSource[aindex].csize;
    m_attachListTarget[aindex].hits= m_attachListSource[aindex].csize;
    m_attachListTarget[aindex].needexp= m_attachListSource[aindex].csize;
    m_attachListTarget[aindex].uptime= m_attachListSource[aindex].uptime;
    m_attachListTarget[aindex].isactive = '1';
    m_mapsAttachDAO[m_flagSource]->addAttach(m_attachListTarget[aindex]);
    //预留需要将source的文件地址写入target,后续加字段
  }
}

void Mover::completeNovel()
{
  if(comfirmTransaction())
  {
    if(m_opfBuilder.confirmOptFile(m_currentConfig->filepath.c_str(), boost::lexical_cast<long>(m_articleTarget.articleid)))
    {
      for (int ci = m_lastTargetChapterCount; ci < m_sourceChapterRecCount; ++ci)
      {
        if(ci == 0)
        {
          analyseNextPage(2, ci);//后一章节
        }
        else if(ci > 0 && ci < m_targetChapterRecCount -1 )
        {
          analyseNextPage(1, ci);//有后一章节,且有前一章节
          analyseNextPage(2, ci);
        }
        else if(ci == m_targetChapterRecCount - 1 )
        {
          analyseNextPage(1, ci);//有前一章节
        }
        m_mapsBuilder[m_flag]->createChapter(*m_currentConfig, m_articleTarget, m_chapterListTarget[ci]);
        usleep(m_currentConfig->sleepchapter * 1000);
      }
      m_mapsBuilder[m_flag]->createIndex(m_articleTarget, m_chapterListTarget, m_targetChapterRecCount);
      m_currentConfig->lastupdate.assign(m_articleListSource[m_articleIndex].lastupdate);
    }
    else
    {
      printf("[30107][%s]Create opf file faild!\n",m_flag.c_str());
    }
  }
}
